package cn.spring.framework.redis.core.redis;

import cn.spring.framework.redis.config.LzmhRedisProperties;
import cn.spring.framework.redis.constant.Constants;
import cn.spring.framework.redis.core.FillCache;
import cn.spring.framework.redis.core.Refresher;
import cn.spring.framework.redis.core.SetOperator;
import cn.spring.framework.redis.excutor.AsyncCacheExecutor;
import cn.spring.framework.redis.excutor.CacheExecutor;
import cn.spring.framework.redis.excutor.FutureAdapter;
import cn.spring.framework.redis.excutor.SyncCacheExecutor;
import cn.spring.framework.redis.service.RedisService;
import org.springframework.util.CollectionUtils;

import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;

/**
 * @author xingkong
 * @Title: RedisSetOperator
 * @Description:
 * @date 2021/11/15 9:57
 */
public class RedisSetOperator extends AbstractRedisOperator implements SetOperator {
    /**
     * 异步任务执行器
     */
    protected CacheExecutor<Set<String>> asyncCacheExecutor = new AsyncCacheExecutor<>();

    public RedisSetOperator(LzmhRedisProperties lzmhRedisProperties, RedisService redisService) {
        super(lzmhRedisProperties, redisService);
    }


    @Override
    public Set<String> sMembers(String key, long expire, Refresher<Set<String>> flusher) {
        return this.sMembers(key, expire, flusher, new SyncCacheExecutor<>()).getData();
    }

    @Override
    public Future<Set<String>> sMembersAsync(String key, long expire, Refresher<Set<String>> flusher) {
        return this.sMembers(key, expire, flusher, this.asyncCacheExecutor);
    }

    @Override
    public Future<Set<String>> sMembersAsync(String key, long expire, Refresher<Set<String>> flusher, ExecutorService executorService) {
        return this.sMembers(key, expire, flusher, new AsyncCacheExecutor<>(executorService));
    }

    private FutureAdapter<Set<String>> sMembers(String key,
                                                long expire,
                                                Refresher<Set<String>> flusher,
                                                CacheExecutor<Set<String>> cacheExecutor) {
        Set<String> smembers = redisService.getCacheSet(key);
        if (!CollectionUtils.isEmpty(smembers)) {
            return FutureAdapter.runAndGetFuture(smembers);
        }

        return (FutureAdapter<Set<String>>) cacheExecutor.executor(() -> this.fillCache(new FillCache<Set<String>>() {
            @Override
            public String getKey() {
                return key;
            }

            @SuppressWarnings("unchecked")
            @Override
            public Set<String> getIgnoreValidData() {
                return (Set<String>) blockIfNeed(key);
            }

            @Override
            public Set<String> getCacheData() {
                //执行具体的获取缓存数据逻辑
                Set<String> data = flusher.refresh();
                //对过期时间进行延长
                long newExpire = expire;
                if (expire != Constants.REDIS_TTL_FOREVER) {
                    newExpire = getExtendExpire(expire);
                }
                //填充缓存
                redisService.setCacheSet(key, newExpire, data);
                return data;
            }
        }));
    }

    @Override
    protected Object getDataIgnoreValid(String key) {
        Set<String> smembers = redisService.getCacheSet(key);
        if (CollectionUtils.isEmpty(smembers)) {
            return null;
        }
        return smembers;
    }
}
